package com.birdy.user.action;

import com.alibaba.fastjson.JSONObject;
import com.birdy.annotation.LogTimeUsed;
import com.birdy.con.AppConst;
import com.birdy.dto.Response;
import com.birdy.jwt.code.JWTResponseCode;
import com.birdy.jwt.exception.TokenExpiredException;
import com.birdy.jwt.service.ITokenService;
import com.birdy.jwt.vo.Pair;
import com.birdy.user.service.IUserService;
import com.birdy.util.AppTokenHelper;
import com.birdy.vo.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author birdy
 */
@Slf4j
@RestController
@RequestMapping("/user/")
public class UserAction {
    @Autowired
    private ITokenService tokenService;
    @Autowired
    private IUserService userService;

    /**
     * 通过code和userinfo进行落库
     * @param body code with userinfo
     * @return new jwt token
     */
    @LogTimeUsed
    @PostMapping("login_with_info")
    public Response loginWithInfo(@RequestBody String body) {
        log.info("{}", body);
        JSONObject parseObject = JSONObject.parseObject(body);
        if (parseObject.containsKey(AppConst.KEY_CODE)
                && parseObject.containsKey(AppConst.KEY_USER_INFO)) {
            String code = parseObject.getString(AppConst.KEY_CODE);
            UserInfo userInfo = parseObject.getObject(AppConst.KEY_USER_INFO, UserInfo.class);
            // code换取openid, session_key
            AppTokenHelper appTokenHelper = new AppTokenHelper();
            Response openIdAndSessionKey = appTokenHelper.getOpenIdAndSessionKey(code);
            // 接口调用失败
            if (openIdAndSessionKey.getRes() != Response.SUCCESS) {
                return openIdAndSessionKey;
            }
            String openid = (String) openIdAndSessionKey.getData().get(AppConst.KEY_OPENID);
            String sessionKey = (String) openIdAndSessionKey.getData().get(AppConst.KEY_SESSION_KEY);
            String userRegister = userService.checkUserInfoRegister(openid);
            // 注册过了
            if (userRegister != null) {
                int ret = userService.updateUserInfo(openid, userInfo);
                log.info("already register, ret:{}", ret);
            } else {
                int ret = userService.addUserInfo(openid, userInfo);
                log.info("a new boy, ret:{}", ret);
            }
            try {
                String token = tokenService.createToken(sessionKey, new Pair(AppConst.KEY_OPENID, openid));
                return Response.builder().res(Response.SUCCESS).msg("success")
                        .data(AppConst.KEY_TOKEN, token).build();
            } catch (Exception e) {
                log.error(e.getMessage());
                return Response.builder().res(Response.FAILED).msg("服务器繁忙，请稍后再试").build();
            }
        }
        return Response.builder().res(Response.FAILED).msg("failed").build();
    }

    /**
     * 检查用户通过wx.login()的用户code，根据此code拿到openid and session_key
     * openid拿到之后去检查数据库是否注册，如果没注册就注册
     * session_key作为jwt的id，拿到之后与openid一起作为jwt的信息成分
     * @param code 用户通过wx.login()的code
     * @return success: 新建的token fail: 失败原因
     */
    @LogTimeUsed
    @GetMapping("check_code")
    public Response checkUserCode(@RequestParam String code) {
        Response openIdAndSessionKey = new AppTokenHelper().getOpenIdAndSessionKey(code);
        if (openIdAndSessionKey.getRes() != Response.SUCCESS) {
            return openIdAndSessionKey;
        }
        String openid = (String) openIdAndSessionKey.getData().get(AppConst.KEY_OPENID);
        String sessionKey = (String) openIdAndSessionKey.getData().get(AppConst.KEY_SESSION_KEY);
        String userRegister = userService.checkUserRegister(openid);
        // 没注册过
        if (userRegister == null) {
            int res = userService.addUser(openid);
            if (res == -1) {
                return Response.builder().res(Response.FAILED).msg("服务器繁忙，请稍后再试").build();
            }
        }
        try {
            String token = tokenService.createToken(sessionKey, new Pair(AppConst.KEY_OPENID, openid));
            return Response.builder().res(Response.SUCCESS).msg("success")
                    .data(AppConst.KEY_TOKEN, token).build();
        } catch (Exception e) {
            log.error(e.getMessage());
            return Response.builder().res(Response.FAILED).msg("服务器繁忙，请稍后再试").build();
        }
    }

    /**
     * 检验用户token是否过期
     * @param token 存在小程序缓存中的jwt token
     * @return 返回token过期态
     */
    @GetMapping("check_auth")
    public Response checkAuth(@RequestParam String token) {
        return tokenService.verifyToken(token) ?
                Response.builder().res(Response.SUCCESS)
                        .msg(JWTResponseCode.SUCCESS_CODE.getMessage()).build() :
                Response.builder().res(JWTResponseCode.TOKEN_TIMEOUT_CODE.getCode())
                        .msg(JWTResponseCode.TOKEN_TIMEOUT_CODE.getMessage()).build();
    }

    /**
     * 刷新token的有效期
     * @param token 缓存在小程序中的token
     * @return success: 返回最新的token fail: 返回token过期提示
     */
    @GetMapping("refresh_auth")
    public Response refreshAuth(@RequestParam String token) {
        String refreshToken;
        try {
            refreshToken = tokenService.refreshToken(token);
        }catch (TokenExpiredException e) {
            return Response.builder().res(JWTResponseCode.TOKEN_TIMEOUT_CODE.getCode())
                    .msg(JWTResponseCode.TOKEN_TIMEOUT_CODE.getMessage()).build();
        }
        return Response.builder().res(JWTResponseCode.SUCCESS_CODE.getCode())
                .msg(JWTResponseCode.SUCCESS_CODE.getMessage())
                .data("token", refreshToken).build();
    }
    @GetMapping("hello")
    public Response hello() {
        return Response.builder().res(Response.SUCCESS).msg("hello").build();
    }
}
